package com.quanyan.club.service.impl;

import com.alibaba.fastjson.JSON;
import com.quanyan.api.APIResponse;
import com.quanyan.club.constants.ClubConstants;
import com.quanyan.club.entity.db.*;
import com.quanyan.club.entity.vo.req.ReqClubWidthdrawApplyList;
import com.quanyan.club.entity.vo.resp.RespClubBindAccount;
import com.quanyan.club.entity.vo.resp.RespClubWidthdrawApply;
import com.quanyan.club.entity.vo.resp.RespClubWidthdrawRecord;
import com.quanyan.club.mapper.*;
import com.quanyan.club.service.ClubAccountService;
import com.quanyan.club.service.ClubWidthdrawService;
import com.quanyan.club.service.CppService;
import com.quanyan.common.Plugin.PageObj;
import com.quanyan.common.constants.Constants;
import com.quanyan.common.exception.BizException;
import com.quanyan.common.utils.Limit;
import com.quanyan.common.utils.ObjectUtil;
import com.quanyan.common.utils.StringUtil;
import com.quanyan.mq.enums.MqConsumerStatus;
import com.quanyan.orderpay.request.ReqWithdrawApply;
import com.quanyan.orderpay.request.WithdrawPayInfo;
import com.quanyan.orderpay.response.mq.WithdrawTransferNotify;
import com.quanyan.orderpay.service.OrderPayService;
import com.quanyan.pay.enums.PayWayEnum;
import com.quanyan.redisCluster.config.RedisTemplate;
import com.quanyan.redisCluster.utils.RedisConstants;
import com.quanyan.redisCluster.utils.RedisKey;
import com.quanyan.search.utils.Constant;
import com.quanyan.user.response.RespUserInfoBase;
import com.quanyan.user.response.RespUserInfoDetail;
import org.mybatis.spring.SqlSessionTemplate;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletRequest;
import javax.validation.constraints.NotNull;
import java.math.BigDecimal;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * Created by zhuo.shi on 2016/6/20.
 */
@Service
public class ClubWidthdrawServiceImpl extends BaseServiceImpl implements ClubWidthdrawService{

    private static Logger logger = LoggerFactory.getLogger(ClubWidthdrawServiceImpl.class);

    @Autowired
    private TbClubWithdrawalsRecordMapper withdrawalsRecordMapper;
    @Autowired
    private TbClubWithdrawalsApplyMapper clubWithdrawalsApplyMapper;
    @Autowired
    private TbClubBindAccountMapper clubBindAccountMapper;
    @Autowired
    private TbClubOnlineAccountMapper clubOnlineAccountMapper;
    @Autowired
    private TbClubOnlineAccountStreamMapper clubOnlineAccountStreamMapper;
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private SqlSessionTemplate sqlSessionTemplate;
    @Autowired
    private TbClubMapper clubMapper;

    @Autowired
    private OrderPayService orderPayService;

    @Autowired
    private TbClubWithdrawalsApplyMapper withdrawalsApplyMapper;
    @Autowired
    private CppService cppService;
    @Autowired
    private ClubAccountService clubAccountService;

    /**
     * 绑定俱乐部提现账号
     * @param clubId            俱乐部ID
     * @param uid               进行绑定动作用户ID
     * @param accountType       账号类型：1 支付宝， 2 微信
     * @param accountNo         用户微信授权后返回的openid 或 支付宝账号
     * @param name              微信或者支付宝账号认证用户姓名
     * @param phone             微信或支付宝账号对应的电话号码
     * @return
     */
    @Override
    public APIResponse bindClubAccount(@NotNull Integer clubId, @NotNull Integer uid, @NotNull Integer accountType,
                                   @NotNull String accountNo, String name, String phone, String accountAvatar) {
        boolean isBind = isAccountBind(clubId, uid, accountType, accountNo);
        if (isBind){
            return APIResponse.returnFail("已经绑定提现账户了！");
        }
        TbClubBindAccount account = new TbClubBindAccount();
        account.setClubId(clubId);
        account.setUid(uid);
        account.setAccountType(accountType);
        account.setAccountNo(accountNo);
        account.setAccountAvatar(accountAvatar);
        RespUserInfoBase userinfo = getUserInfoBase(uid);
        if (userinfo == null ){
            return APIResponse.returnFail("用户不存在！");
        }
        if (accountType == 1 && !name.equals(userinfo.getRealName())){ //支付宝验证姓名真实性
            return APIResponse.returnFail("提交的账户姓名和实名认证的真实姓名不一致！");
        }
        account.setName(name);
        account.setPhone(phone);
        int ret = clubBindAccountMapper.insertSelective(account);
        return ret == 1?APIResponse.returnSuccess():APIResponse.returnFail("绑定失败！");
    }

    /**
     * 查询俱乐部被会长绑定的账号列表
     * @param clubId            俱乐部ID
     * @return
     */
    @Override
    public List<TbClubBindAccount> getClubBindAccounts(@NotNull Integer clubId) {
        TbClubBindAccountExample example = new TbClubBindAccountExample();
        example.createCriteria().andClubIdEqualTo(clubId).andIsDeleteEqualTo(false);
        return clubBindAccountMapper.selectByExample(example);
    }

    /**
     * 获取要解绑的俱乐部绑定账户，获取后发送手机验证码到绑定的手机，并写入phone:validatecode到redis
     * @param clubId 俱乐部id
     * @return
     */
    @Override
    public RespClubBindAccount getClubUnbindAccount(Integer clubId) {
        RespClubBindAccount respClubBindAccount = new RespClubBindAccount();

        TbClub club = clubMapper.selectByPrimaryKey(clubId);

        if (club == null || club.getIsDelete()==1) {
            throw new BizException("俱乐部已解散！");
        }
        RespUserInfoDetail userInfo = getUserDetailInfo(club.getUid());

        if (userInfo == null) {
            throw new BizException("用户不存在！");
        }

        Byte verifyStatus = userInfo.getNameVerifyStatusDe();
        logger.warn("------------------1verifyStatus=" + verifyStatus);
        if (verifyStatus != null) {
            respClubBindAccount.setIdentityStatus(verifyStatus);
        } else {
            respClubBindAccount.setIdentityStatus((byte) 0);
        }
        List<TbClubBindAccount> accounts = getClubBindAccounts(clubId);
        if (accounts == null || accounts.isEmpty()){
            return respClubBindAccount;
        }
        TbClubBindAccount account = accounts.get(0);
        String phone = account.getPhone();
        respClubBindAccount.setId(account.getId());
        respClubBindAccount.setAccountType(account.getAccountType());
        respClubBindAccount.setAccountNo(account.getAccountNo());
        respClubBindAccount.setAvailableWithdrawCount(this.getAvailableWithdrawCount(account.getClubId()));
        respClubBindAccount.setName(account.getName());
        respClubBindAccount.setPhone(phone);
        respClubBindAccount.setUsableAmount(this.getUsableWidthdrawAmount(account.getClubId()));
        respClubBindAccount.setBind(true);
        respClubBindAccount.setAccountAvatar(account.getAccountAvatar());

        if (respClubBindAccount.getAccountType() == 1) {        //支付宝显示用户头像
            respClubBindAccount.setAccountAvatar(userInfo.getIcon());
        }else { //微信显示微信头像，如果没有再显示用户头像
            if (StringUtil.isBlankOrNull(respClubBindAccount.getAccountAvatar())) {
                respClubBindAccount.setAccountAvatar(userInfo.getIcon());
            }
        }

        return respClubBindAccount;
    }

    /**
     * 解绑俱乐部提现账号
     * @param clubId            俱乐部ID
     * @param uid               进行绑定动作用户ID
     * @param accountType       账号类型：1 支付宝， 2 微信
     * @param accountNo         用户微信授权后返回的openid 或 支付宝账号
     * @return
     */
    @Override
    public Boolean unbindClubAccount(@NotNull Integer clubId, @NotNull Integer uid,
                                     @NotNull Integer accountType, @NotNull String accountNo) {
        boolean isBind = isAccountBind(clubId, uid, accountType, accountNo);
        if (!isBind){
            return false;
        }
        TbClubBindAccountExample example = new TbClubBindAccountExample();
        example.createCriteria().andClubIdEqualTo(clubId).andUidEqualTo(uid).
                andAccountTypeEqualTo(accountType).andAccountNoEqualTo(accountNo);
        int ret = clubBindAccountMapper.deleteByExample(example);
        return ret > 0;
    }

    /**
     * 判断某个账号是否已经绑定
     */
    @Override
    public Boolean isAccountBind(Integer clubId, Integer uid, Integer accountType, String accountNo){
        TbClubBindAccountExample example = new TbClubBindAccountExample();
        example.createCriteria().andClubIdEqualTo(clubId).andUidEqualTo(uid).andAccountTypeEqualTo(accountType).
                andAccountNoEqualTo(accountNo).andIsDeleteEqualTo(false);
        int count = clubBindAccountMapper.countByExample(example);
        return count>0;
    }

    /**
     * 查询俱乐部可提现金额
     * @param clubId            俱乐部ID
     * @return
     */
    @Override
    public BigDecimal getUsableWidthdrawAmount(@NotNull Integer clubId) {
        TbClubOnlineAccountExample example = new TbClubOnlineAccountExample();
        example.createCriteria().andClubIdEqualTo(clubId).andIsDeleteEqualTo(Constants.IS_DELETE_FALSE);
        List<TbClubOnlineAccount> onlineAccounts = clubOnlineAccountMapper.selectByExample(example);
        if (onlineAccounts != null && onlineAccounts.size() > 0){
            return onlineAccounts.get(0).getMoneyUsable();
        }
        return BigDecimal.ZERO;
    }

    /**
     * 俱乐部申请提现（支付宝、微信提现申请）
     * @param applyUid          申请人uid
     * @param clubId            俱乐部ID
     * @param amount            提现金额
     * @param accountType       提现类型 1 支付宝， 2 微信
     * @param accountNo         账号，微信openid, 支付宝账号
     * @return
     */
    @Override
    @Transactional
    public Boolean applyClubWithdraw(int applyUid, Integer clubId, BigDecimal amount, Integer accountType, String accountNo, HttpServletRequest request) {
        TbClubWithdrawalsApply withdrawalsApply = new TbClubWithdrawalsApply();
        withdrawalsApply.setClubId(clubId);
        withdrawalsApply.setMoney(amount);
        withdrawalsApply.setAccountType(accountType.byteValue());
        withdrawalsApply.setWithdrawalsAccount(accountNo);
        withdrawalsApply.setApplyNo(clubId + "" + System.currentTimeMillis());  //申请批次号
        withdrawalsApply.setAuditStatus(ClubConstants.AUDIT_STATUS_DEALING);    //提现状态
        withdrawalsApply.setWithdrawalsStatus(ClubConstants.WITHDRAWALS_STATUS_DEAL_BY_SYS);//待付款
        withdrawalsApply.setIsDelete(Constants.IS_DELETE_FALSE);
        withdrawalsApply.setUid(applyUid);
        TbClub club = clubMapper.selectByPrimaryKey(clubId);
        int uid = club.getUid();
        RespUserInfoBase user = getUserInfoBase(uid);
        if (user != null){
            String realName = user.getRealName();
            if (StringUtil.isBlankOrNull(realName)){
                logger.warn("提现俱乐部id={}, accountNo={}没有实名认证", clubId, accountNo);
                return false;
            }
            withdrawalsApply.setWithdrawalsName(realName);    //提现账户对应的真实姓名
            withdrawalsApply.setWithdrawalsPhone(user.getMobile());     //提现账户对应的手机号码
        }else {
            return false;   //俱乐部主席不存在
        }

        //先更新余额，调用支付系统，确保支付系统返回失败，可以回滚, 更新tb_club_online_account，可用金额，冻结金额
        Map<String, Object> map = new HashMap<>();
        map.put("clubId", clubId);
        map.put("withdrawAmount", amount);
        int updateret = sqlSessionTemplate.update("updateClubAccountFreezeAndUsableFund", map);
        if (updateret <= 0){
            throw new BizException("冻结提现资金失败！");
        }
        //向支付系统提交提现申请
        ReqWithdrawApply reqWithdrawApply = new ReqWithdrawApply();
        reqWithdrawApply.setSourceSystemCode(Constants.CLUB_SYSTEM_CODE);
        reqWithdrawApply.setSourceBusinessCode(Constants.CLUB_WITHDRAW_BUSINESS_CODE);
        reqWithdrawApply.setPayType(accountType);
        WithdrawPayInfo withdrawPayInfo = new WithdrawPayInfo();
        withdrawPayInfo.setApplyNo(withdrawalsApply.getApplyNo());
        withdrawPayInfo.setAccountNo(accountNo);
        withdrawPayInfo.setName(user.getRealName()); //"朱春杰"
        withdrawPayInfo.setAmount(amount);
        withdrawPayInfo.setPhone(user.getMobile());
        withdrawPayInfo.setBalance(getClubOnlineBalance(clubId));
        withdrawPayInfo.setApplyTime(new Date());
        withdrawPayInfo.setClubId(clubId);
        withdrawPayInfo.setWithdrawDesc(club.getClubName() + "资金提现");
        reqWithdrawApply.setWithdrawPayInfo(withdrawPayInfo);
        String serverUrl = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort();
        reqWithdrawApply.setNotifyUrl(serverUrl + "/api/club/callBack/withdrawNotify");
        reqWithdrawApply.setAppVersion(request.getHeader("APPVersion"));
        logger.warn("---withdraw req---" + JSON.toJSONString(reqWithdrawApply));
        APIResponse apiResponse = orderPayService.applyWithdraw(reqWithdrawApply);
        if (apiResponse  == null || !apiResponse.isRet()){
            logger.error("向支付系统提交提现申请失败，{}" + JSON.toJSONString(apiResponse));
            throw new BizException(apiResponse.getErrmsg());
        }else {
            //记录支付系统返回的提现申请流水号
            withdrawalsApply.setWithdrawNo(String.valueOf(apiResponse.getData()));
        }
        logger.warn("---withdraw apply---" + JSON.toJSONString(withdrawalsApply));

        int ret = clubWithdrawalsApplyMapper.insertSelective(withdrawalsApply);
        if (ret == Constants.IS_YES){
            //记录此俱乐部的提现次数
            recordWithdrawCount(clubId);

            //记录俱乐部线上资金流水，用于对账
            TbClubOnlineAccountExample onlineAccountExample = new TbClubOnlineAccountExample();
            onlineAccountExample.createCriteria().andClubIdEqualTo(clubId);
            TbClubOnlineAccount onlineAccount = clubOnlineAccountMapper.selectByExample(onlineAccountExample).get(0);
            TbClubOnlineAccountStream stream = new TbClubOnlineAccountStream();
            stream.setClubOnlineAccountId(onlineAccount.getId());
            stream.setSerialNo(withdrawalsApply.getApplyNo());
            //stream.setOutTradeNo();
            stream.setClubId(clubId);
            stream.setStatus((byte)2); //处理中
            stream.setType((byte)0);   //支出
            stream.setOutputOnline(BigDecimal.ZERO);
            stream.setPreAmount(onlineAccount.getMoneyTotal());
            stream.setSufAmount(onlineAccount.getMoneyTotal());
            stream.setRemark("提现申请");
            stream.setCreateTime(new Date());
            clubOnlineAccountStreamMapper.insertSelective(stream);
//            微信自动提现
//            if (accountType.intValue() == PayWayEnum.PAY_WAY_WEICHAT.getPayId().intValue()){
//                //发起微信转账
//                WithdrawPayInfo payInfo = new WithdrawPayInfo();
//                payInfo.setAccountNo(accountNo);
//                payInfo.setAmount(amount);
//                payInfo.setApplyNo(withdrawalsApply.getApplyNo());
//                payInfo.setPayAmount(amount);
//                payInfo.setPayOpInfo("系统自动打款");
//                payInfo.setWithdrawNo(String.valueOf(apiResponse.getData()));
//
//                APIResponse response = orderPayService.transferFundByWechat(payInfo);
//                if (!response.isRet()){
//                    logger.warn("俱乐部{}微信系统自动打款失败，原因：{}" + response.getErrmsg());
//                }
//            }
            return true;
        }
        return false;
    }

    /**
     * 获取俱乐部提现申请列表
    */
    @Override
    public PageObj<List<RespClubWidthdrawApply>> getWithdrawApplies(ReqClubWidthdrawApplyList reqApplyList) {
        TbClubWithdrawalsApplyExample example = new TbClubWithdrawalsApplyExample();
        TbClubWithdrawalsApplyExample.Criteria criteria = example.createCriteria();
        if (reqApplyList.getStartTime() != null){
            criteria.andCreateTimeGreaterThanOrEqualTo(reqApplyList.getStartTime());
        }
        if (reqApplyList.getEndTime() != null){
            criteria.andCreateTimeLessThanOrEqualTo(reqApplyList.getEndTime());
        }
        if (!StringUtil.isBlankOrNull(reqApplyList.getApplyNo())){
            criteria.andApplyNoEqualTo(reqApplyList.getApplyNo());
        }
        if (!StringUtil.isBlankOrNull(reqApplyList.getRealName())){
            criteria.andWithdrawalsNameEqualTo(reqApplyList.getRealName());
        }
        if (!StringUtil.isBlankOrNull(reqApplyList.getClubName())){
            criteria.andClubNameEqualTo(reqApplyList.getClubName());
        }
        if (!StringUtil.isBlankOrNull(reqApplyList.getPhone())){
            criteria.andWithdrawalsPhoneEqualTo(reqApplyList.getPhone());
        }
        if (!StringUtil.isBlankOrNull(reqApplyList.getAccountNo())){
            criteria.andWithdrawalsAccountEqualTo(reqApplyList.getAccountNo());
        }
        int total = clubWithdrawalsApplyMapper.countByExample(example);
        int pageNo = reqApplyList.getPageNum() + 1;
        example.setLimit(Limit.buildLimit(pageNo, reqApplyList.getPageSize()));
        List<TbClubWithdrawalsApply> applies = clubWithdrawalsApplyMapper.selectByExample(example);
        List<RespClubWidthdrawApply> applyList = new ArrayList<>();
        for (TbClubWithdrawalsApply apply : applies){
            RespClubWidthdrawApply respApply = new RespClubWidthdrawApply();
            respApply.setApplyTime(apply.getCreateTime());
            respApply.setApplyNo(apply.getApplyNo());
            respApply.setRealName(apply.getWithdrawalsName());
            respApply.setClubName(apply.getClubName());
            respApply.setPhone(apply.getWithdrawalsPhone());
            respApply.setAccountNo(apply.getWithdrawalsAccount());
            respApply.setPayType(apply.getAccountType());
            respApply.setAmount(apply.getMoney());  //提现金额
            respApply.setBalance(getClubOnlineBalance(apply.getClubId()));                 //余额
            int status = apply.getWithdrawalsStatus();
            switch (status){
                case ClubConstants.WITHDRAWALS_STATUS_DEAL_BY_SYS: //待付款
                    respApply.setStatus("待付款");break;
                case ClubConstants.WITHDRAWALS_STATUS_DEAL_BY_THIRDPARTY: //支付宝或微信处理中
                    respApply.setStatus("处理中");break;
                case ClubConstants.WITHDRAWALS_STATUS_SUCCESS:
                    respApply.setStatus("付款成功"); break;
                case ClubConstants.WITHDRAWALS_STATUS_FAIL: //处理失败
                    respApply.setStatus("处理失败 " + apply.getRemark());
            }
            applyList.add(respApply);
        }
        return PageObj.create(total, pageNo, reqApplyList.getPageSize(), applyList);
    }

    private BigDecimal getClubOnlineBalance(int clubId){
        TbClubOnlineAccountExample example = new TbClubOnlineAccountExample();
        example.createCriteria()
                .andClubIdEqualTo(clubId)
                .andIsDeleteEqualTo(Constants.IS_DELETE_FALSE);
        List<TbClubOnlineAccount> onlineAccounts = clubOnlineAccountMapper.selectByExample(example);
        if (onlineAccounts != null && !onlineAccounts.isEmpty()){
            return onlineAccounts.get(0).getMoneyUsable();
        }
        return BigDecimal.ZERO;
    }

    /**
     * 记录俱乐部账户当天提现次数
     * @param clubId                俱乐部ID
     */
    private void recordWithdrawCount(Integer clubId){
        RedisKey redisKey = new RedisKey(RedisConstants.CLUB_FAMILY_KEY, clubId + ClubConstants.WITHDRAW_REDIS_KEY);
        //计算当前时间离23:59:59.999的毫秒数，设置此键，并设置过期时间，以至于此键在当天零点自动删除
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        String currentDate0 = sdf.format(new Date()) + " 23:59:59";
        int expire = 0;
        try {
            sdf.applyPattern("yyyy-MM-dd HH:mm:ss");
            Date today0 = sdf.parse(currentDate0);
            expire = (int)((today0.getTime() - new Date().getTime())/1000);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        if (!redisTemplate.exists(redisKey)){
            redisTemplate.setWithExpireTime(redisKey, 1, expire);
        }else {
            redisTemplate.setWithExpireTime(redisKey, (Integer) redisTemplate.get(redisKey) + 1, expire);
        }
    }

    /**
     * 获取俱乐部当天可提现的次数
     * @param clubId
     * @return
     */
    private int getAvailableWithdrawCount(Integer clubId){
        RedisKey redisKey = new RedisKey(RedisConstants.CLUB_FAMILY_KEY, clubId + ClubConstants.WITHDRAW_REDIS_KEY);
        if (redisTemplate.exists(redisKey)){
            return 3 - (Integer) redisTemplate.get(redisKey);
        }
        return 3; //默认一天可以提现3次
    }

    /**
     * 俱乐部微信提现审核通过
     * @param clubId            俱乐部ID
     * @param amount            提现金额    单位：元
     * @param openid            用户授权的微信openid
     * @param name              提现账号对应用户姓名
     * @param withdrawNo           提现申请流水号
     * @return
     */
    @Override
    @Transactional(isolation = Isolation.READ_COMMITTED)
    public APIResponse withdrawByWeixinPassAudit(Integer clubId, BigDecimal amount, String openid, String name, String withdrawNo) {
        //1. 验证提现账户
        TbClubBindAccountExample example = new TbClubBindAccountExample();
        example.createCriteria()
                .andClubIdEqualTo(clubId)
                .andAccountNoEqualTo(openid)
                .andIsDeleteEqualTo(false);
        if( clubBindAccountMapper.countByExample(example) <= 0 ){
            return APIResponse.returnFail("提现账户不存在");
        }

        //2. 调用支付系统，企业付款给微信用户
        //APIResponse response = orderPayService.transferFundByWechat(openid, withdrawNo, amount.multiply(new BigDecimal(100)), "提现"); //金额单位转化为：分

        /**以下操作改在ClubWithdrawConsumer里面处理*/
        //3. 判断转账状态，
        //3.1 如果微信转账返回失败，更改申请提现状态为失败
//        if (!response.isRet()){
//            updateApplyWithdrawStatus(clubId, withdrawNo, ClubConstants.WITHDRAWALS_STATUS_FAIL, response.getErrmsg());
//            return response;
//        }
//        //3.2 如果微信转账返回成功，从俱乐部线上账户扣除提现金额
//        Map<String, Object> map = new HashMap<>();
//        map.put("clubId", clubId);
//        map.put("withdrawAmount", amount);
//        int updateret = sqlSessionTemplate.update("updateClubAccountTotalAndFreezeFund", map);
//        if (updateret == Constants.IS_YES){
//            //4. 记入提现记录表
//            TbClubWithdrawalsRecord withdrawalsRecord = new TbClubWithdrawalsRecord();
//            withdrawalsRecord.setClubId(clubId);
//            withdrawalsRecord.setAccountType(ClubConstants.WITHDRAW_BY_WEIXIN);
//            withdrawalsRecord.setWithdrawalsName(name);
//            withdrawalsRecord.setWithdrawalsAccount(openid);
//            withdrawalsRecord.setMoney(amount);
//            int ret = withdrawalsRecordMapper.insertSelective(withdrawalsRecord);
//            //5. 更改申请提现状态为成功
//            if (ret == 1){
//                updateApplyWithdrawStatus(clubId, withdrawNo, ClubConstants.WITHDRAWALS_STATUS_SUCCESS, "提现成功");
//            }
//        }else{
//            updateApplyWithdrawStatus(clubId, withdrawNo, ClubConstants.WITHDRAWALS_STATUS_FAIL, "更新俱乐部资金出错");
//        }
        return null;
    }

    /**
     * 更新提现申请的提现状态
     * @param clubId                俱乐部id
     * @param withdrawNo            支付系统返回的提现申请流水号
     * @param withdrawalsStatus     状态
     * @return
     */
    private boolean updateApplyWithdrawStatus(Integer clubId, String withdrawNo, byte withdrawalsStatus, String remark){
        TbClubWithdrawalsApplyExample example = new TbClubWithdrawalsApplyExample();
        example.createCriteria().andClubIdEqualTo(clubId).andWithdrawNoEqualTo(withdrawNo).andIsDeleteEqualTo(Constants.IS_DELETE_FALSE);
        TbClubWithdrawalsApply apply = new TbClubWithdrawalsApply();
        apply.setWithdrawalsStatus(withdrawalsStatus);
        apply.setRemark(remark);
        int ret = clubWithdrawalsApplyMapper.updateByExampleSelective(apply, example);
        return ret == 1;
    }

    /**
     *  俱乐部提现记录列表
     * @param clubId            俱乐部ID
     * @param status            提现状态，处理中or完成
     * @return
     */
    @Override
    public List<RespClubWidthdrawRecord> getClubWidthdrawRecords(Integer clubId, Integer status, Integer pageNo, Integer pageSize) {
        List<TbClubBindAccount> bindAccounts = getClubBindAccounts(clubId);
        String bindAccountName = "";
        if (bindAccounts != null && bindAccounts.size()>0) {
             bindAccountName = bindAccounts.get(0).getName();
        }
        TbClubWithdrawalsApplyExample example = new TbClubWithdrawalsApplyExample();
        TbClubWithdrawalsApplyExample.Criteria criteria = example.createCriteria();
        criteria.andClubIdEqualTo(clubId);
        if (status == 1){   //处理中
            criteria.andWithdrawalsStatusIn(Arrays.asList(ClubConstants.WITHDRAWALS_STATUS_DEAL_BY_SYS, ClubConstants.WITHDRAWALS_STATUS_DEAL_BY_THIRDPARTY));
            example.setOrderByClause(" create_time desc");
        }
        if(status == 2){    //已完成
            criteria.andWithdrawalsStatusIn(Arrays.asList(ClubConstants.WITHDRAWALS_STATUS_SUCCESS, ClubConstants.WITHDRAWALS_STATUS_FAIL));
            example.setOrderByClause(" update_time desc");
        }

        example.setLimit(Limit.buildLimit(pageNo, pageSize));
        List<TbClubWithdrawalsApply> applies = clubWithdrawalsApplyMapper.selectByExample(example);
        List<RespClubWidthdrawRecord> records = new ArrayList<>();
        for (TbClubWithdrawalsApply apply : applies){
            RespClubWidthdrawRecord record = new RespClubWidthdrawRecord();
            record.setAccountNo(apply.getWithdrawalsAccount());
            record.setAmount(apply.getMoney());
            byte type = apply.getAccountType();
            if (type == ClubConstants.WITHDRAW_BY_ALIPAY) {
                record.setAccountType("支付宝（" + getAccountString(apply.getWithdrawalsAccount()) + ")");
            }
            if (type == ClubConstants.WITHDRAW_BY_WEIXIN){
                record.setAccountType("微信（" + bindAccountName + "）");
            }
            record.setAppyTime(apply.getCreateTime());
            record.setFinishTime(apply.getUpdateTime());
            record.setStatus(apply.getWithdrawalsStatus());
            records.add(record);
        }
        return records;
    }

    private String getAccountString(String accountNo){
        if (StringUtil.isBlankOrNull(accountNo) || accountNo.length() < 7){
            return accountNo;
        }
        StringBuilder sb = new StringBuilder();
        try {
            char[] chars = accountNo.toCharArray();
            for (int i = 0; i < chars.length; i++){
                if (i > 2 && i < 7){
                    sb.append("*");
                }else {
                    sb.append(chars[i]);
                }
            }
        }catch (Exception e){
            return accountNo;
        }
        return sb.toString();
    }

    /**
     * 俱乐部提现记录总数
     * @param clubId            俱乐部ID
     * @param status            提现状态，处理中or完成
     * @return
     */
    @Override
    public Integer countClubWidthdrawRecords(Integer clubId, Integer status) {
        TbClubWithdrawalsApplyExample example = new TbClubWithdrawalsApplyExample();
        TbClubWithdrawalsApplyExample.Criteria criteria = example.createCriteria();
        criteria.andClubIdEqualTo(clubId);
        if (status == 1){   //处理中
            criteria.andWithdrawalsStatusIn(Arrays.asList(ClubConstants.WITHDRAWALS_STATUS_DEAL_BY_SYS, ClubConstants.WITHDRAWALS_STATUS_DEAL_BY_THIRDPARTY));
        }
        if(status == 2){    //已完成
            criteria.andWithdrawalsStatusIn(Arrays.asList(ClubConstants.WITHDRAWALS_STATUS_SUCCESS, ClubConstants.WITHDRAWALS_STATUS_FAIL));
        }
        return clubWithdrawalsApplyMapper.countByExample(example);
    }

    @Override
    @Transactional
    public APIResponse withdrawCallbackNotify(WithdrawTransferNotify notify) {

        //1. 过滤，只处理本系统的提现业务
        String systemCode = notify.getSourceSystemCode();
        String bussinessCode = notify.getSourceBusinessCode();
        if (!systemCode.equals(Constants.CLUB_SYSTEM_CODE) || !bussinessCode.equals(Constants.CLUB_WITHDRAW_BUSINESS_CODE)) {
            logger.warn("非俱乐部提现");
            return APIResponse.returnSuccess();
        }

        String withdrawNo = notify.getWithdrawNo(); //支付系统生成的提现申请流水号

        //2. 查询出此条俱乐部提现申请
        TbClubWithdrawalsApplyExample example = new TbClubWithdrawalsApplyExample();
        TbClubWithdrawalsApplyExample.Criteria criteria = example.createCriteria();
        criteria
                .andWithdrawNoEqualTo(withdrawNo)
                .andWithdrawalsStatusEqualTo((byte)3)
                .andIsDeleteEqualTo(Constants.IS_DELETE_FALSE);
        if (withdrawalsApplyMapper.countByExample(example) > 0){  //已经提现成功了，再次回调，跳过
            return APIResponse.returnSuccess();
        }
        example.clear();
        criteria = example.createCriteria();
        criteria
                .andWithdrawNoEqualTo(withdrawNo)
                .andIsDeleteEqualTo(Constants.IS_DELETE_FALSE);
        if (notify.getTag()){
            criteria.andWithdrawalsStatusNotEqualTo((byte)3);        //公司已付款，提现已成功，不能再次更新俱乐部线上资金
        }else {
            criteria.andWithdrawalsStatusNotEqualTo((byte)4);       //已经失败了，再次回调，不再恢复冻结资金
        }
        List<TbClubWithdrawalsApply> applies = withdrawalsApplyMapper.selectByExample(example);
        if (applies == null || applies.isEmpty()) {
            return APIResponse.returnFail("提现回调直接返回：可能原因，1. 提现流水号{}不存在，2. 或者公司已付款，提现已成功，重复的回调，3. 或已更新提现失败状态，再次回调不再次恢复冻结资金" + withdrawNo);
        }
        TbClubWithdrawalsApply record = applies.get(0);

        int clubId = record.getClubId();        //俱乐部id
        String reason = notify.getReason();     //付款成功或失败原因
        if(null == reason) {
            reason = "";
        }
        BigDecimal amount = notify.getAmount(); //提现金额，返回的单位为: 元
        amount = amount.setScale(2, BigDecimal.ROUND_HALF_UP);

        if (notify.getTag()) {      //如果付款成功
            //3. 更新俱乐部线上账户资金
//            APIResponse response = clubAccountService.updateClubOnlineAccountBalance(clubId, null, record.getApplyNo(), notify.getTsn(), amount, "财务打款", false, -1);
//            if (!response.isRet()){
//                logger.error("俱乐部提现回调，扣除俱乐部{}线上金额失败。", record.getClubId());
//                reason += "俱乐部提现回调，扣除线上金额失败"+response.getErrmsg();
//            }
            Map<String, Object> map = new HashMap<>();
            map.put("clubId", clubId);
            map.put("withdrawAmount", amount.doubleValue());
            logger.warn("提现金额：" + map);
            int updateret = sqlSessionTemplate.update("updateClubAccountTotalAndFreezeFund", map);
            if (updateret != 1) {
                logger.error("俱乐部提现回调，扣除俱乐部{}线上金额失败。", record.getClubId());
                reason += "俱乐部提现回调，扣除线上金额失败";
                recordWithdrawStream(clubId, record, 3,"提现到账失败");  //处理失败
                notify.setTag(false);  //更新资金失败
            }
            else {
                //4. 记录俱乐部提现流水
                TbClubWithdrawalsRecord withdrawalsRecord = new TbClubWithdrawalsRecord();
                withdrawalsRecord.setApplyNo(notify.getApplyNo());
                withdrawalsRecord.setBatchNo(notify.getBatchNo());
                withdrawalsRecord.setClubId(clubId);
               // withdrawalsRecord.setAccountType(ClubConstants.WITHDRAW_BY_WEIXIN);
                withdrawalsRecord.setWithdrawalsName(notify.getName());
                withdrawalsRecord.setWithdrawalsAccount(notify.getAccountNo());
                withdrawalsRecord.setMoney(amount);
                withdrawalsRecord.setBalance(getUsableWidthdrawAmount(clubId)); //此俱乐部线上账户的余额
                withdrawalsRecord.setUid(record.getUid());
                withdrawalsRecordMapper.insertSelective(withdrawalsRecord);

                recordWithdrawStream(clubId, record, 1,"提现到账成功");  //处理成功，记录流水
                logger.warn("提现到账成功：" + JSON.toJSONString(notify));

                //推送提现成功消息
                cppService.pushWithdrawNotifyMessage(record, true, reason);

                pushAuthMsg(clubId);
            }
        }else {
            //恢复冻结资金
            Map<String, Object> map = new HashMap<>();
            map.put("clubId", clubId);
            map.put("withdrawAmount", amount);
            logger.warn("提现回调参数：{}", JSON.toJSON(notify));
            logger.warn("解冻资金===========》");
            int updateret = sqlSessionTemplate.update("updateClubAccountUsablelAndFreezeFund", map);
            if (updateret != 1) {
                logger.error("俱乐部提现回调，解冻俱乐部{}线上金额失败。", record.getClubId());
                reason += "俱乐部提现回调，解冻线上金额失败";
            }

            recordWithdrawStream(clubId, record, 3,"提现到账失败"+reason);  //处理失败

            //推送提现失败消息
            cppService.pushWithdrawNotifyMessage(record, false, reason);
        }

        //5. 更新此笔提现记录
        if (notify.getTag()) {
            record.setWithdrawalsStatus((byte) 3);  //付款成功
        } else {
            record.setWithdrawalsStatus((byte) 4);  //付款失败
        }
        record.setBatchNo(notify.getBatchNo());     //支付系统生成的批次号
        record.setRemark(reason);       //第三方支付系统返回的，成功或者失败原因 + 自己系统的原因
        record.setAuditStatus((byte) 2);             //审核通过
        record.setUpdateTime(null);
        withdrawalsApplyMapper.updateByPrimaryKeySelective(record);

        return APIResponse.returnSuccess();
    }

    private void recordWithdrawStream(int clubId, TbClubWithdrawalsApply withdrawalsApply, int status, String remark){

        //记录俱乐部线上资金流水，用于对账
        TbClubOnlineAccountExample onlineAccountExample = new TbClubOnlineAccountExample();
        onlineAccountExample.createCriteria().andClubIdEqualTo(clubId);
        TbClubOnlineAccount onlineAccount = clubOnlineAccountMapper.selectByExample(onlineAccountExample).get(0);
        TbClubOnlineAccountStream stream = new TbClubOnlineAccountStream();
        stream.setClubOnlineAccountId(onlineAccount.getId());
        stream.setSerialNo(withdrawalsApply.getApplyNo());
        //stream.setOutTradeNo();
        stream.setClubId(clubId);
        stream.setStatus((byte)status); //处理状态
        stream.setType((byte)-1);   //提现回调
        stream.setOutputOnline(withdrawalsApply.getMoney());
        if (status == 3) {
            stream.setPreAmount(onlineAccount.getMoneyTotal());
            stream.setSufAmount(onlineAccount.getMoneyTotal());
        }
        if (status == 1){
            stream.setPreAmount(onlineAccount.getMoneyTotal().add(withdrawalsApply.getMoney()));
            stream.setSufAmount(onlineAccount.getMoneyTotal());
        }
        stream.setCreateTime(new Date());
        stream.setRemark(remark);
        logger.warn("------------------提现，记录 online account 流水：" + JSON.toJSONString(stream));
        clubOnlineAccountStreamMapper.insertSelective(stream);
    }

    private void pushAuthMsg(int clubId){
        RedisKey redisKey = new RedisKey(Constants.CLUB_SYSTEM, clubId + ClubConstants.WITHDRAW_REDIS_AUTH);
        if (!redisTemplate.exists(redisKey)){
            TbClub tbClub = clubMapper.selectByPrimaryKey(clubId);
            if (tbClub.getIsDelete() == 1 || tbClub.getStatus() !=0){
                return;
            }
            String msg = "您的俱乐部\"" + tbClub.getClubName() + "\"已经获得实名认证！";
            cppService.pushClubCommonMsg(tbClub.getLogoUrl(), msg, Arrays.asList(tbClub.getUid()));
            redisTemplate.set(redisKey, clubId);
        }
    }
}
